What is a block in Ruby?
在Ruby中的區塊(Block)是什麼?
今天來介紹一個在Ruby中少數不是物件的Block。
Block是do...end
和{...}
包住的程式碼片段,Block中的程式碼會不會被執行主要是要看它「夥伴」的臉色,唯有「夥伴」(伴隨的程式)將控制權交給block時他才會被執行,舉下面程式碼說明會更加清楚。
def say_my_name(name)
puts "My name is #{name}"
end
say_my_name("John") {puts "hello world"}
# => My name is John
雖然我們在say_my_name
方法後面接了block,但這段程式碼並不會被執行,因為控制權並沒有被轉讓給block,要怎麼讓block被執行呢?
要使用yield
方法,控制權會轉讓給block執行,我們將上面的方法改寫在前後都加上yield
並再次執行。
def say_my_name(name)
yield
puts "My name is #{name}"
yield
end
say_my_name("John") {puts "hello world"}
# =>hello world
# =>My name is John
# =>hello world
因為呼叫say_my_name
方法後,碰到yield
,控制權轉讓給了block,而去執行了puts "hello world"
,再回來執行puts "My name is #{name}"
,之後又碰到yield
,再一次執行控制權轉讓,所以最終結果印出了兩次hello world。
相信剛接觸Ruby的人都看過下面這種特別的寫法
3.times { puts "hello world" }
#=> hello world
#=> hello world
#=> hello world
# 也可以這樣寫
3.times do puts "hello world" end
數字3在Ruby中是個物件,而可以使用times方法,將後面的這段Block當作參數,就可以印出三次hello world。而block為什麼能被執行呢?不是說要用yield嗎,可以猜得到的是times方法裡面一定有yield將控制權轉讓出來。
另外block還有另外一個神奇的用途,能夠接收參數,接收的參數用||
這個特殊的符號包住,yield轉讓控制權的時候能夠將參數送出來,看以下例子示範。
def animals
yield "Cat"
yield "Dog"
end
animals { |x| puts "Hello, #{x}" }
#=> Hello, Cat
#=> Hello, Dog
兩次yield代入了不同的參數給後面的block,也就印出了不同結果。
而|x|
裡面的x
是Block裡面的區域變數,離開Block之後是無法存取的。
def animals
yield "Cat"
yield "Dog"
end
animals { |x| puts "Hello, #{x}" }
#=> Hello, Cat
#=> Hello, Dog
puts x #=> Error undefined local variable or method `x'
Block是一段以do...end
和{...}
包含的程式碼片段,並不會主動執行,要靠yield方法來轉移控制權給Block,Block有自己的Scope,定義在Block內的變數並不能由Block外部取得。